package com.gjt.dlmall.product.controller;

import com.gjt.dlmall.product.service.CategoryService;
import com.gjt.dlmall.product.vo.CategoryVo;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;
import java.util.UUID;

/**
 * @author gjt
 * @version 1.0
 * @date 2021/11/27 13:25
 */
@Controller
public class IndexController {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 闭锁
     * @return
     * @throws InterruptedException
     */
    @ResponseBody
    @GetMapping("/lockDoor")
    public String lockDoor() throws InterruptedException {
        RCountDownLatch door = redissonClient.getCountDownLatch("door");
        door.trySetCount(5);
        door.await();//等待其他的闭锁都完成
        return "关门了";
    }

    /**
     * 人走了
     * @param id
     * @return
     */
    @ResponseBody
    @GetMapping("/gogo/{id}")
    public String goLockDoor(@PathVariable("id") Long id){
        RCountDownLatch door = redissonClient.getCountDownLatch("door");
        door.countDown();//计数-1
        return id+"桌的人都走了....";

    }
    /**
     * 信号量  获取
     * @return
     * @throws InterruptedException
     */
    @ResponseBody
    @GetMapping("/park")
    public String park() throws InterruptedException {
        RSemaphore semaphore = redissonClient.getSemaphore("park");
        //当停车场的车位减少为0时，还想获取车位，必须要等 go方法调用时，释放一个车位，才能继续执行
        semaphore.acquire();//占有一个车位
        return "ok";
    }

    /**
     * 信号量 释放 可做限流
     * @return
     */
    @ResponseBody
    @GetMapping("/go")
    public String go(){
        RSemaphore semaphore = redissonClient.getSemaphore("park");
        semaphore.release();//释放
        return "ok";
    }
    /**
     * 写锁
     * @return
     */
    @ResponseBody
    @GetMapping("/write")
    public String writeValue(){
        //获取一把锁
        RReadWriteLock lock = redissonClient.getReadWriteLock("rw-lock");
        //加 写锁
        String s="";
        RLock writeLock = lock.writeLock();
        try{
            //1、改数据加 写锁，读数据加 读 锁
            writeLock.lock();
            System.out.println("写锁加锁成功..."+Thread.currentThread().getId());
            s = UUID.randomUUID().toString();
            Thread.sleep(15000);
            redisTemplate.opsForValue().set("writeValue",s);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //释放锁
            writeLock.unlock();
            System.out.println("写锁...释放.."+Thread.currentThread().getId());
        }
        return s;
    }
    /**
     * 读锁
     * @return
     */
    @ResponseBody
    @GetMapping("/read")
    public String readValue(){
        RReadWriteLock lock = redissonClient.getReadWriteLock("rw-lock");
        String s="";
        //加 读锁
        RLock readLock = lock.readLock();
        readLock.lock();
        try {
            System.out.println("读锁..加锁成功..."+Thread.currentThread().getId());
            s = redisTemplate.opsForValue().get("writeValue");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            readLock.unlock();
            System.out.println("释放..读锁.."+Thread.currentThread().getId());
        }
        return s;
    }

    /**
     * 使用 Redisson 演示可重入锁
     * @return
     */
    @ResponseBody
    @GetMapping("/hello")
    public String hello(){
        //获取一把锁
        RLock lock = redissonClient.getLock("my-lock");
        //加锁
        lock.lock(); // 加锁
        try{
            System.out.println("加锁成功，执行业务..."+Thread.currentThread().getId());
            Thread.sleep(10000);
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            //解锁   Thread.currentThread().getId() 获取线程id
            System.out.println("解锁..."+ Thread.currentThread().getId());
            lock.unlock();
        }

        return "hello";
    }
    @GetMapping({"/", "/index.html"})
    public String indexPage(Model model){
        List<CategoryVo> categoryEntityList = categoryService.getLevel1Categorys();
        model.addAttribute("categorys",categoryEntityList);
        //默认加上前缀和后缀：classPath:/templates/index.html
        return "index";
    }
}
